package com.yuandengta.yomall.order.service.impl;

import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.payment.page.models.AlipayTradePagePayResponse;
import com.yuandengta.yomall.order.constant.OrderStatusEnum;
import com.yuandengta.yomall.order.entity.PaymentInfoEntity;
import com.yuandengta.yomall.order.service.AliPayService;
import com.yuandengta.yomall.order.service.OrderService;
import com.yuandengta.yomall.order.service.PaymentInfoService;
import com.yuandengta.yomall.order.vo.PayAsyncVO;
import com.yuandengta.yomall.order.vo.PayVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 支付宝支付接口实现 {@link AliPayServiceImpl}
 *
 * @author Kevin
 * @email: 178676392@qq.com
 */
@Slf4j
@Service
public class AliPayServiceImpl implements AliPayService {

    @Value("${alipay.returnUrl}")
    private String returnUrl;

    @Value("${alipay.timeoutExpress}")
    private String timeoutExpress;

    @Autowired
    private OrderService orderService;

    @Autowired
    private PaymentInfoService paymentInfoService;

    /**
     * 支付
     * @param orderSn
     * @return
     */
    @Override
    public String pay(String orderSn) {
        PayVO payVO = orderService.getOrderPay(orderSn);
        payVO.setSubject("优品订单支付");
        payVO.setBody("");

        try {
            AlipayTradePagePayResponse response = Factory.Payment.Page()
                    // 订单允许的最晚付款时间，逾期将关闭交易
                    .optional("timeout_express", timeoutExpress)
                    .pay(payVO.getSubject(), payVO.getOut_trade_no(), payVO.getTotal_amount(), returnUrl);
            // body: 支付宝的收银台页面
            return response.body;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 支付成功异步回调
     * @param vo
     * @param request
     * @return
     * @throws Exception
     */
    @Override
    public String payNotify(PayAsyncVO vo, HttpServletRequest request) throws Exception {
        // 验签
        Boolean signVerified = verifyNotify(request);
        // 验证成功
        if (signVerified) {
            log.info("异步通知验签成功...");
            // 保存交易流水
            PaymentInfoEntity paymentInfoEntity = new PaymentInfoEntity();
            paymentInfoEntity.setAlipayTradeNo(vo.getTrade_no());
            paymentInfoEntity.setOrderSn(vo.getOut_trade_no());
            paymentInfoEntity.setSubject(vo.getSubject());
            paymentInfoEntity.setTotalAmount(new BigDecimal(vo.getTotal_amount()));
            paymentInfoEntity.setPaymentStatus(vo.getTrade_status());
            Date parseDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(vo.getNotify_time());
            paymentInfoEntity.setCallbackTime(parseDate);
            paymentInfoService.save(paymentInfoEntity);

            // 修改订单状态信息
            if ("TRADE_SUCCESS".equals(vo.getTrade_status()) || "TRADE_FINISHED".equals(vo.getTrade_status())) {
                String outTradeNo = vo.getOut_trade_no();
                orderService.updateOrderStatus(outTradeNo, OrderStatusEnum.PAYED.getCode());
            }

            // 只要收到支付宝异步通知，告知订单支付成功，返回success，支付宝就不会再通知
            return "success";
        } else {
            log.error("异步通知验签失败...");
            return "fail";
        }
    }

    /**
     * 异步通知验签
     * @param request
     * @return
     * @throws Exception
     */
    public Boolean verifyNotify(HttpServletRequest request) throws Exception {
        log.info("异步通知验签...");
        Map<String,String> params = new HashMap<String,String>();
        Map<String,String[]> requestParams = request.getParameterMap();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }

        // 异步通知验签
        Boolean result = Factory.Payment.Common().verifyNotify(params);

        return result;
    }

    /**
     * 关闭交易
     * @param outTradeNo
     * @throws Exception
     */
    @Override
    public void close(String outTradeNo) throws Exception {
        log.info("支付宝关闭交易...");
        Factory.Payment.Common().close(outTradeNo);
    }
}
